package com.example.mous;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.view.ViewConfiguration;
import android.widget.Toast;

public class TouchPadView extends View {
    private ExecutorService executor;
    private GestureDetector gestureDetector;
    private boolean isLeftPressed = false;
    private float lastX, lastY;
    private DataOutputStream dataOutputStream;
    private Socket socket;
    private float touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    private int activePointers = 0;
    private float wheelAreaWidth = 0.15f; // 右侧15%宽度作为滑轮区域
    private boolean isWheelScroll = false;
    private float lastWheelY;
    private static final float WHEEL_SENSITIVITY = 0.2f;

    public TouchPadView(Context context, AttributeSet attrs) {
        super(context, attrs);
        executor = Executors.newSingleThreadExecutor();
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public void onLongPress(MotionEvent e) {
                sendMouseEvent((byte) 3); // 右键按下
                sendMouseEvent((byte) 4); // 右键释放
            }
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                sendMouseEvent((byte) 1); // 左键按下
                sendMouseEvent((byte) 2); // 左键释放
                return true;
            }
        });
    }
    public synchronized void setSocket(Socket socket) throws IOException {
        closeResources(); // 关闭旧连接
        this.socket = socket;
        socket.setTcpNoDelay(true);
        this.dataOutputStream = new DataOutputStream(socket.getOutputStream());
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        gestureDetector.onTouchEvent(event);
        float x = event.getX();
        boolean isInWheelArea = x >= getWidth() * (1 - wheelAreaWidth);

        if (isInWheelArea) {
            handleWheelEvent(event);
            return true; // 消费事件
        }
        gestureDetector.onTouchEvent(event);


        int action = event.getActionMasked();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                activePointers = 1;
                handleTouchDown(event);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                activePointers++;
                if (activePointers == 2) {
                    handleTwoPointersDown();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (activePointers == 1) {
                    handleSingleTouchMove(event);
                } else if (activePointers == 2) {
                    handleTwoPointersMove(event);
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                activePointers = 0;
                handleTouchUp();
                break;
            case MotionEvent.ACTION_POINTER_UP:
                activePointers--;
                if (activePointers == 1) {
                    handleSinglePointerAfterUp(event);
                }
                break;
        }
        return true;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制滑轮区域
        Paint paint = new Paint();
        paint.setColor(Color.argb(30, 0, 0, 0));
        float areaLeft = getWidth() * (1 - wheelAreaWidth);
        canvas.drawRect(areaLeft, 0, getWidth(), getHeight(), paint);
    }


    private void handleWheelEvent(MotionEvent event) {
        int action = event.getActionMasked();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                isWheelScroll = true;
                lastWheelY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                if (isWheelScroll) {
                    float deltaY = event.getY() - lastWheelY;
                    lastWheelY = event.getY();
                    int steps = (int) (deltaY * WHEEL_SENSITIVITY);
                    if (steps != 0) {
                        sendWheelEvent(-steps); // 方向调整
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isWheelScroll = false;
                break;
        }
    }

    private void sendWheelEvent(int steps) {
        if (!isConnected()) {
            showDisconnectedToast();
            return;
        }
        executor.execute(() -> {
            try {
                synchronized (this) {
                    if (dataOutputStream != null) {
                        dataOutputStream.writeByte(6); // 滚轮命令
                        dataOutputStream.writeInt(steps);
                        dataOutputStream.flush();
                    }
                }
            } catch (IOException e) {
                closeResources();
            }
        });
    }




    private void handleTouchDown(MotionEvent event) {
        lastX = event.getX();
        lastY = event.getY();
    }
    private void handleSingleTouchMove(MotionEvent event) {
        float deltaX = event.getX() - lastX;
        float deltaY = event.getY() - lastY;
        lastX = event.getX();
        lastY = event.getY();
        sendMoveEvent(deltaX, deltaY);
    }
    private void handleTwoPointersDown() {
        if (!isLeftPressed) {
            sendMouseEvent((byte) 1);
            isLeftPressed = true;
        }
    }
    private void handleTwoPointersMove(MotionEvent event) {
        if (event.getPointerCount() >= 2) {
            float x0 = event.getX(0);
            float y0 = event.getY(0);
            float x1 = event.getX(1);
            float y1 = event.getY(1);
            float centerX = (x0 + x1) / 2;
            float centerY = (y0 + y1) / 2;
            float deltaX = centerX - lastX;
            float deltaY = centerY - lastY;
            sendMoveEvent(deltaX, deltaY);
            lastX = centerX;
            lastY = centerY;
        }
    }
    private void handleTouchUp() {
        if (isLeftPressed) {
            sendMouseEvent((byte) 2);
            isLeftPressed = false;
        }
    }
    private void handleSinglePointerAfterUp(MotionEvent event) {
        lastX = event.getX(event.getActionIndex());
        lastY = event.getY(event.getActionIndex());
    }
    private void sendMoveEvent(float deltaX, float deltaY) {
        if (!isConnected()) {
            showDisconnectedToast();
            return;
        }
        executor.execute(() -> {
            try {
                synchronized (this) {
                    if (dataOutputStream != null) {
                        dataOutputStream.writeByte(0);
                        dataOutputStream.writeFloat(deltaX);
                        dataOutputStream.writeFloat(deltaY);
                        dataOutputStream.flush();
                    }
                }
            } catch (IOException e) {
                closeResources();
            }
        });
    }
    private void sendMouseEvent(byte action) {
        if (!isConnected()) {
            showDisconnectedToast();
            return;
        }
        executor.execute(() -> {
            try {
                synchronized (this) {
                    if (dataOutputStream != null) {
                        dataOutputStream.writeByte(action);
                        dataOutputStream.flush();
                    }
                }
            } catch (IOException e) {
                closeResources();
            }
        });
    }
    synchronized boolean isConnected() {
        return socket != null && socket.isConnected() && !socket.isClosed();
    }
    private void showDisconnectedToast() {
        post(() -> Toast.makeText(getContext(), "连接已断开", Toast.LENGTH_SHORT).show());
    }
    private synchronized void closeResources() {
        try {
            if (socket != null) {
                socket.close();
                socket = null;
            }
            if (dataOutputStream != null) {
                dataOutputStream.close();
                dataOutputStream = null;
            }
            showDisconnectedToast();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        executor.shutdownNow();
        closeResources();
    }
    public synchronized DataOutputStream getDataOutputStream() {
        return dataOutputStream;
    }
}